package net.nanbean.nplayer;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.net.Uri;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.webkit.WebView;
import android.widget.VideoView;

public class SamiParser {
	private static final String TAG = "Nplayer";
	private static final int SUBTITLE_DISPLAY_INT = 1000;
	
	private int bSubtitleExist;
	private String strSmiLang1st=null;
	private String strSmiLang2nd=null;
	private String strSmiType1st=null;
	private String strSmiType2nd=null;
	private int nSmiSync1st[];
	private int nSmiSync2nd[];
	private String strSmiText1st[];
	private String strSmiText2nd[];
	private int nSubtitleTotalText=-1;
	private int nSubtitleTotalText2nd=-1;
	private int nCurrentSmiNo=1;
	private int nTextSize=20;
	
	private String encodingType = "UTF-8";
	
	private WebView webView4Subtitle;
	private VideoView parentVideoView4Subtitle;
	
	public SamiParser(Uri videoURI, VideoView parentVideoView, WebView subTitleView) {
		strSmiText1st = new String[10000];
		nSmiSync1st = new int[10000];
		
		strSmiText2nd = new String[10000];
		nSmiSync2nd = new int[10000];
		
		parseSubtitle(videoURI.getPath());
		webView4Subtitle = subTitleView;
		parentVideoView4Subtitle = parentVideoView;
		
		webView4Subtitle.setBackgroundColor(0);
	}
	
	public boolean isSubtitleExist() {
		if(bSubtitleExist > 0)
			return true;
		else
			return false;

	}
	
	public void showSubtitle(boolean show) {
		if(show)
		{
			webView4Subtitle.setVisibility(View.VISIBLE);
			webView4Subtitle.postDelayed(onSubtitleDisplay, SUBTITLE_DISPLAY_INT);
		}
		else
			webView4Subtitle.setVisibility(View.GONE);
	}
	
	public void setSubtitleSize(int size) {
		nTextSize = size;
	}
	
	public void setSubtitle(int currentPosition) {
		
		if(nCurrentSmiNo==1) {
			int curText = 0;
			
			for(curText = 0; curText < nSubtitleTotalText; curText++)
			{
				if( currentPosition >= nSmiSync1st[curText] && currentPosition <= nSmiSync1st[curText+1])
					break;
			}
	
			if(curText>=nSubtitleTotalText || strSmiText1st[curText]==null)
			{
				webView4Subtitle.loadDataWithBaseURL("test!!!!!!", "&nbsp;", "text/html", "UTF-8", null);
			}
			else
			{
				String bodyText = "<body style='text-align: center; color: #ffffff; font-size: " + nTextSize + "px;'>";
				webView4Subtitle.loadDataWithBaseURL("test!!!!!!", bodyText + strSmiText1st[curText], "text/html", "UTF-8", null);
			}
		}
		else if(nCurrentSmiNo==2) {
			int curText = 0;
			
			for(curText = 0; curText < nSubtitleTotalText2nd; curText++)
			{
				if( currentPosition >= nSmiSync2nd[curText] && currentPosition <= nSmiSync2nd[curText+1])
					break;
			}
	
			if(curText>=nSubtitleTotalText2nd || strSmiText2nd[curText]==null)
			{
				webView4Subtitle.loadDataWithBaseURL("test!!!!!!", "&nbsp;", "text/html", "UTF-8", null);
			}
			else
			{
				String bodyText = "<body style='text-align: center; color: #ffffff; font-size: " + nTextSize + "px;'>";
				webView4Subtitle.loadDataWithBaseURL("test!!!!!!", bodyText + strSmiText2nd[curText], "text/html", "UTF-8", null);
				Log.d(TAG, "Text : " + strSmiText2nd[curText]);
			}			
		}
	}
	
	private void parseSubtitle(String url) {
		
		Log.v(TAG, "url : " + url);
		
    	int dotPos = url.lastIndexOf(".");
    	String subtitleName = null;
    	
    	if(dotPos>0)
    	{
	    	subtitleName = url.substring(0, dotPos);
	    	
	    	subtitleName = subtitleName + ".smi";
    	}
    	
    	Log.v(TAG, "subtitleName : " + subtitleName);
    	
    	if(subtitleName != null) {
    		File subtitleFile = new File(subtitleName);
    	
	    	if(subtitleFile.exists())
	    	{
	    		samiReadEncodingType(subtitleName);
	    		
	    		bSubtitleExist = samiReadHead(subtitleName);
	    		
	    		Log.v(TAG, "sami file exist");
	    		
	    		if(strSmiType1st != null)
	        		samiReadType1st(subtitleName);
	    	}
	    	else
	    	{
	    		bSubtitleExist = 0;
	    		Log.v(TAG, "sami file is not exist");
	    	}
    	}
    	else {
    		bSubtitleExist = 0;
    		Log.v(TAG, "can't find file");
    	}
	}
	
	private int samiReadEncodingType(String smiFilePath)
	{
		try {
			FileInputStream fHead = new FileInputStream(smiFilePath);
			
			// file read(4Byte)
			byte[] BOM = new byte[4];
			fHead.read(BOM, 0, 4);
			    	
			// check file encoding
			if( (BOM[0] & 0xFF) == 0xEF && (BOM[1] & 0xFF) == 0xBB && (BOM[2] & 0xFF) == 0xBF )
			{
				Log.i(TAG, "UTF-8");
				encodingType = "UTF-8";
			}
			else if( (BOM[0] & 0xFF) == 0x00 && (BOM[1] & 0xFF) == 0x00 && 
			         (BOM[0] & 0xFF) == 0xFE && (BOM[1] & 0xFF) == 0xFF )
			{
				Log.i(TAG, "UTF-32BE");
				encodingType = "UTF-32BE";
			}
			else if( (BOM[0] & 0xFF) == 0xFF && (BOM[1] & 0xFF) == 0xFE && 
			         (BOM[0] & 0xFF) == 0x00 && (BOM[1] & 0xFF) == 0x00 )
			{
				Log.i(TAG, "UTF-32LE");
				encodingType = "UTF-32LE";
			}
			else if( (BOM[0] & 0xFF) == 0xFF && (BOM[1] & 0xFF) == 0xFE )
			{
				Log.i(TAG, "UTF-16LE");
				encodingType = "UTF-16LE";
			}
			else if( (BOM[0] & 0xFF) == 0xFE && (BOM[1] & 0xFF) == 0xFF )
			{
				Log.i(TAG, "UTF-16BE");
				encodingType = "UTF-16BE";
			}
			else
			{
				Log.i(TAG, "EUC-KR");
				encodingType = "EUC-KR";
			}
			
			Log.d(TAG, "encodingType : " + encodingType);
			
			fHead.close();
	   	} catch(IOException e) {
			Log.e(TAG, "error in reading smi file", e);
	        return 0;
		}
		
		return 0;
	}
	
    private int samiReadHead(String smiFilePath)
    {
    	strSmiLang1st = null;
    	strSmiType1st = null;
    	strSmiLang2nd = null;
    	strSmiType2nd = null;
    	
    	int nTotalNumLang = 0;
    	
    	try {
	    	BufferedReader subtitleFile = new BufferedReader(new InputStreamReader(new FileInputStream(smiFilePath), encodingType));

    		/*
    		FileInputStream fin = new FileInputStream(smiFilePath); 
    		Reader reader = new InputStreamReader(fin, "euc-kr"); 
    		BufferedReader smiFile = new BufferedReader(reader);
    		*/
    		//BufferedReader smiFile=new BufferedReader(new FileReader(smiFilePath));
    		
	    	String readLine = null;
	    	
	    	while((readLine = subtitleFile.readLine()) != null)
	    	{
	    		//readLine = readLine.toUpperCase();
	    		
	    		//Log.v(TAG, "read result : " + readLine);
	    		if(readLine.startsWith("."))
	    		{
	    			//Log.v(TAG, "read result : " + readLine);
	    			
    			
	    			if(readLine.matches("(?i).*name.*"))
	    			{
		    			String[] arr2 = readLine.split(";");
		    			
		    			Log.v(TAG, "read result : " + readLine);
	    				Log.v(TAG, "index is : " + readLine.indexOf("(?i).*name.*"));
	    				for(int i=0; i<arr2.length; i++)
	    				{
	    					if(arr2[i].matches("(?i).*name.*"))
	    					{
	    						if(strSmiLang1st == null)
	    						{
	    							strSmiLang1st = arr2[i].substring(arr2[i].indexOf(':') + 1);
	    							strSmiType1st = arr2[0].substring(1, arr2[0].indexOf(' '));
		    						Log.v(TAG, "strSmiLang1st name : " + strSmiLang1st);
		    						Log.v(TAG, "strSmiType1st type : " + strSmiType1st);
	    							nTotalNumLang++;
	    						}
	    						else if(strSmiLang2nd == null)
	    						{
	    							strSmiLang2nd = arr2[i].substring(arr2[i].indexOf(':') + 1);
	    							strSmiType2nd = arr2[0].substring(1, arr2[0].indexOf(' '));
		    						Log.v(TAG, "smiLang2nd name : " + strSmiLang2nd);
		    						Log.v(TAG, "smiType2nd lang : " + strSmiType2nd);
	    							nTotalNumLang++;
	    							break; // support only 2 subtitle
	    						}
	    						else
	    						{
	    							Log.w(TAG, "smiLang is full!!!!");
	    							break;
	    						}
	    					}
	    					
	    				}
	    			}
	    		}
	    		
	    		if(readLine.matches("(?i).*</HEAD>.*"))
	    			break;
	    	}
	    	subtitleFile.close();
	    	
    	} catch(IOException e) {
    		Log.e(TAG, "error in reading smi file", e);
            return 0;
    	}
    	
    	return nTotalNumLang;
    }
    
    private void samiReadType1st(String smiFilePath)
    {
//    	boolean isSkip = false;
//    	int nSyncDet = 0;
//    	int syncCntPerLine = 0;
//    	int nSyncBlcokCnt = 0;
//    	int nExistSync = 0;
//    	int continue_smisync = 0;
    	
//    	int nExistPClass = 0;
    	
//    	String langtype = null;
    	
    	long prevTime = SystemClock.elapsedRealtime();
    	
    	try {

    		
    		FileInputStream fis = new FileInputStream(smiFilePath);
    		
	    	BufferedReader smiFile = new BufferedReader(new InputStreamReader(fis,encodingType));
	    	//BufferedReader smiFile = new BufferedReader(new FileReader(smiFilePath));
	    	String readLineByte = null;
//	    	String readLineUpper = null;
	    	
	    	
	    	String regex_sync_class_string = "<SYNC Start=(.*?)><P Class=(.*?)>(.*?)$";
	    	
	    	Pattern p_regex_sync_class_string = Pattern.compile(regex_sync_class_string, Pattern.CASE_INSENSITIVE);
	    	
	    	String Class = null;
	    	
	    	while((readLineByte = smiFile.readLine()) != null) {
	    		
		    	Matcher m = p_regex_sync_class_string.matcher(readLineByte);
		    	
//		    	while (m.find()) {
		    	if(m.find()) {
		    		
		    		String Start = m.group(1);
		    		Class = m.group(2);
		    		String Script = m.group(3);
		    		
		    		
		    		/*
		    		Log.d(TAG, "Start : " + Start);
		    		Log.d(TAG, "Class : " + Class);
		    		Log.d(TAG, "Script : " + Script);
		    		*/
		    		
		    		if(strSmiType1st.equals(Class)) {
			    		nSubtitleTotalText++;
			    		nSmiSync1st[nSubtitleTotalText] = Integer.parseInt(Start);
			    		strSmiText1st[nSubtitleTotalText] = Script;
		    		}
			    	else if(strSmiType2nd.equals(Class)) {
			    		nSubtitleTotalText2nd++;
			    		nSmiSync2nd[nSubtitleTotalText2nd] = Integer.parseInt(Start);
			    		strSmiText2nd[nSubtitleTotalText2nd] = Script;			    		
			    	}
			    			
		    	}
		    	else {
		    		if(nSubtitleTotalText>=0 && strSmiType1st.equals(Class)) {
		    			strSmiText1st[nSubtitleTotalText] = strSmiText1st[nSubtitleTotalText] + readLineByte;
		    		}
		    		else if(nSubtitleTotalText2nd>=0 && strSmiType2nd.equals(Class)) {
		    			strSmiText2nd[nSubtitleTotalText2nd] = strSmiText2nd[nSubtitleTotalText2nd] + readLineByte;
		    		}
		    		
		    	}
	    	}
	    	

	    	/*
	    	while((readLineByte = smiFile.readLine()) != null)
	    	{
	    		
	    		String readLine = new String(readLineByte.toString().getBytes("UTF-8"), "UTF-8");
	    		
	    		// remove space
	    		readLine = readLine.trim();
	    		
	    		// change to upper case
	    		readLineUpper = readLine.toUpperCase();
	    		
	    		// if encounter </BODY>, end while loop
	    		if(readLineUpper.startsWith("</BODY>"))
	    			break;
	    		

	    		// if encounter <BODY>, skip
	    		if(readLineUpper.startsWith("<BODY>"))
	    			continue;
	    		
	    		nExistSync = 0;
	    		
	    		boolean bStartSync = readLineUpper.matches("(?i).*<SYNC.*");

	    		if( bStartSync && continue_smisync == 0)
	    		{
	    			nSyncDet = 1;
	    			nExistSync = 1;
	    			continue_smisync = 1;
	    		}
	    		else if(!bStartSync && continue_smisync == 0)
	    		{
	    			continue;
	    		}
	    		else if(bStartSync && continue_smisync == 1)
	    		{
	    			nSyncDet = 1;
	    			nExistSync = 1;
	    		}

	    		if(nExistSync == 1)
	    		{
	    			int startPos = 0;
	    			int endPos =0;
	    			
	    			startPos = readLine.indexOf('=');
	    			endPos = readLine.indexOf('>');
	    			//Log.v(TAG, "text : " + readLine);
	    			//Log.v(TAG, "= position : " + startPos);
	    			//Log.v(TAG, "> position : " + endPos);
	    			
	    			if( startPos > 0 && endPos > 0)
	    			{
	    				int tmpSyncTime = Integer.parseInt(readLine.substring(readLine.indexOf('=')+1, readLine.indexOf('>')).trim());
		    			nSubtitleTotalText++;
		    			nSmiSync1st[nSubtitleTotalText]=tmpSyncTime;
		    			strSmiText1st[nSubtitleTotalText]=null;
	    			}
	    		}
	    		
	    		nExistPClass = 0;
	    		boolean bStartPClass = readLineUpper.matches("(?i).*<P CLASS.*");
	    		
	    		if(bStartPClass)
	    			nExistPClass = 1;
	    		
    			int startClassPos = 0;
    			int endClassPos =0;
    			
	    		if(nExistPClass == 1)
	    		{
	    			startClassPos = readLineUpper.indexOf("<P CLASS=");
	    			String tmp = readLineUpper.substring(readLineUpper.indexOf("<P CLASS="));
	    			endClassPos = tmp.indexOf(">");
	    			endClassPos = startClassPos + endClassPos;
	    			
	    			langtype = readLine.substring(startClassPos+9, endClassPos);
	    			//Log.v(TAG, "class : " + langtype);
	    		}
	    		
	    		if(langtype.equals(strSmiType1st))
	    		{
	    			if(strSmiText1st[nSubtitleTotalText]==null)
	    				strSmiText1st[nSubtitleTotalText] = readLine.substring(endClassPos + 1);
	    			else
	    				strSmiText1st[nSubtitleTotalText] = strSmiText1st[nSubtitleTotalText] + readLine.substring(endClassPos);
	    			
	    			//Log.v(TAG, "strSmiText1st[" + nSubtitleTotalText + "] : " + strSmiText1st[nSubtitleTotalText]);
	    		}

	    		if(nExistPClass == 1)
	    		{
	    			
	    		}
	    	}
	    	*/
	    	
	    	smiFile.close();
    	} catch(IOException e) {
    		Log.e(TAG, "error in reading smi file", e);
            return;
    	}
    	
    	Log.v(TAG, "elapsed time = " + (SystemClock.elapsedRealtime() - prevTime));
    }
    
	public void setSubtitleLanguage(int no) {
		nCurrentSmiNo = no;
	}

	private Runnable onSubtitleDisplay=new Runnable() {
    	public void run() {
    		
    		setSubtitle(parentVideoView4Subtitle.getCurrentPosition());
    		
    		Log.v(TAG, "onSubtitleDisplay");

    		if(webView4Subtitle.getVisibility() == View.VISIBLE)
    		{
    			webView4Subtitle.postDelayed(onSubtitleDisplay, SUBTITLE_DISPLAY_INT);
    		}

    	}
    };
}